package cykbt.tests;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import org.junit.Before;
import org.junit.Test;

import cykbt.core.CYK;
import cykbt.core.Cell;
import cykbt.core.ChomskyGrammar;
import cykbt.core.Doublon;
import cykbt.core.Symbol;

public class ChomskyGrammarTest {
	
	ChomskyGrammar grammar;
	
	@Before
	public void initialization(){
		HashMap<Character, Symbol> symbols=new HashMap<Character, Symbol>();
		symbols.put('A', new Symbol('A'));
		symbols.put('B', new Symbol('B'));
		symbols.put('C', new Symbol('C'));
		symbols.put('S', new Symbol('S'));
		symbols.get('S').addDoublon(new Doublon(symbols.get('A'), symbols.get('B')));
		symbols.get('S').addDoublon(new Doublon(symbols.get('B'), symbols.get('B')));
		symbols.get('A').addDoublon(new Doublon(symbols.get('A'), symbols.get('B')));
		symbols.get('A').addDoublon(new Doublon(symbols.get('C'), symbols.get('C')));
		symbols.get('A').addChar('a');
		symbols.get('B').addDoublon(new Doublon(symbols.get('B'), symbols.get('B')));
		symbols.get('B').addDoublon(new Doublon(symbols.get('C'), symbols.get('A')));
		symbols.get('B').addChar('b');
		symbols.get('C').addDoublon(new Doublon(symbols.get('A'), symbols.get('A')));
		symbols.get('C').addDoublon(new Doublon(symbols.get('B'), symbols.get('A')));
		symbols.get('C').addChar('a');
		grammar = new ChomskyGrammar(symbols.values(),symbols.get('S'));
	}
	@Test
	public void testSymbolesDerivantVersChar(){
		assertEquals(grammar.getSymbolsThatCanDeriveTo('a').size(),2);
		assertEquals(grammar.getSymbolsThatCanDeriveTo('b').size(),1);
		assertEquals(grammar.getSymbolsThatCanDeriveTo('c').size(),0);
	}
	@Test
	public void testSymbolesDerivantVersCellules(){
		assertEquals(grammar.getSymbolsThatCanDeriveTo(new Cell(), new Cell()).size(),0);
		Cell c1=new Cell(),c2=new Cell();
		List<Symbol> s1=new ArrayList<Symbol>(),s2=new ArrayList<Symbol>();
		s1.add(new Symbol('A'));
		s2.add(new Symbol('A'));
		s2.add(new Symbol('B'));
		c1.add(s1);
		c2.add(s2);
		assertEquals(grammar.getSymbolsThatCanDeriveTo(new Cell(), new Cell()).size(),0);
		assertEquals(grammar.getSymbolsThatCanDeriveTo(c1, new Cell()).size(),0);
		assertEquals(grammar.getSymbolsThatCanDeriveTo(c1, c1).size(),1);
		assertEquals(grammar.getSymbolsThatCanDeriveTo(c1, c2).size(),3);
		assertEquals(grammar.getSymbolsThatCanDeriveTo(c2, c1).size(),1);
		assertEquals(grammar.getSymbolsThatCanDeriveTo(c2, c2).size(),4);
	}
	@Test
	public void resolveTest(){
		CYK cyk=new CYK(grammar);
		//0
		assertFalse(cyk.solve(""));
		//1
		assertFalse(cyk.solve("a"));
		assertFalse(cyk.solve("b"));
		//2
		assertFalse(cyk.solve("aa"));
		assertTrue(cyk.solve("ab"));
		assertFalse(cyk.solve("ba"));
		assertTrue(cyk.solve("bb"));
		//3
		assertTrue(cyk.solve("aaa"));
		assertTrue(cyk.solve("aab"));
		assertFalse(cyk.solve("aba"));
		assertTrue(cyk.solve("abb"));
		assertTrue(cyk.solve("baa"));
		assertFalse(cyk.solve("bab"));
		assertFalse(cyk.solve("bba"));
		assertTrue(cyk.solve("bbb"));
		//4
		assertTrue(cyk.solve("aaaa"));
		assertTrue(cyk.solve("aaab"));
		assertFalse(cyk.solve("aaba"));
		assertTrue(cyk.solve("aabb"));
		assertTrue(cyk.solve("abaa"));
		assertTrue(cyk.solve("abab"));
		assertFalse(cyk.solve("abba"));
		assertTrue(cyk.solve("abbb"));
		assertTrue(cyk.solve("baaa"));
		assertTrue(cyk.solve("baab"));
		assertFalse(cyk.solve("baba"));
		assertFalse(cyk.solve("babb"));
		assertTrue(cyk.solve("bbaa"));
		assertFalse(cyk.solve("bbab"));
		assertFalse(cyk.solve("bbba"));
		assertTrue(cyk.solve("bbbb"));
	}
}
